package com.edu.internship.util;

import com.edu.internship.glabal.constants.Constants;
import com.edu.internship.glabal.constants.ResultCodeEnum;
import com.edu.internship.glabal.exception.BusinessException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Pattern;

/**
 * code is far away from bug with the animal protecting
 *
 * @author lishiquan
 * @description 字符串工具类
 * @date Create in 2018/2/26 11:03
 */
public class Tools extends StringUtils {

    private static final char SEPARATOR = '_';
    private static final Pattern HTML_PATTERN = Pattern.compile("<.+?>");

    private Tools() {
    }

    /**
     * uuid序列
     *
     * @return uuid
     */
    public static synchronized String createUuidSerial() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 格式化BigDecimal为字符串
     *
     * @param value 入参
     * @return 字符串形式的数值
     */
    public static String bigDecimalToString(BigDecimal value) {
        String returnVal = value.toString();
        int minLength = 4;
        if (returnVal.length() - returnVal.indexOf(Constants.BaseCons.DOT.getCode()) > minLength) {
            returnVal = returnVal.substring(0, returnVal.indexOf(Constants.BaseCons.DOT.getCode()) + 5);
        } else if (!returnVal.contains(Constants.BaseCons.DOT.getCode())) {
            returnVal = returnVal + ".00";
        }
        return returnVal;
    }

    /**
     * 断数组是否为null或空
     *
     * @param array 入参
     * @return true：空数组
     */
    public static boolean isEmptyArray(Object[] array) {
        return Objects.isNull(array) || array.length == 0;
    }

    /**
     * 判断list是否为空列表（null和零长度的字符串都是空）
     *
     * @param list 入参
     * @return true：空列表
     */
    public static <T> boolean isEmptyList(List<T> list) {
        return Objects.isNull(list) || list.isEmpty();
    }

    /**
     * 判断字符串是否为空Map（null和零长度的字符串都是空）
     *
     * @param map 入参
     * @return true：空map
     */
    public static <T> boolean isEmptyMap(Map<String, T> map) {
        return Objects.isNull(map) || map.isEmpty();
    }

    /**
     * 将null对象转化为空串""
     *
     * @param str 入参
     * @return ""-空串
     */
    public static String nullToSpaceStr(String str) {
        if (isBlank(str)) {
            return EMPTY;
        } else {
            return str.trim();
        }
    }

    /**
     * 将null对象转化为0
     *
     * @param obj 入参
     * @return 0
     */
    public static int nullToZero(String obj) {
        if (isBlank(obj)) {
            return 0;
        }
        if (isNumStr(obj)) {
            return Integer.valueOf(obj);
        }
        return 0;
    }

    /**
     * 判断是否为整数
     *
     * @param num 入参
     * @return true: 是整数
     */
    public static boolean isNumStr(String num) {
        return isNotBlank(num) && num.matches("[0-9]+");
    }

    /**
     * 替换掉HTML标签方法
     *
     * @param html 入参
     * @return 字符串
     */
    public static String replaceHtml(String html) {
        if (isBlank(html)) {
            return EMPTY;
        }
        return HTML_PATTERN.matcher(html).replaceAll(EMPTY);
    }

    /**
     * 缩略字符串（不区分中英文字符）
     *
     * @param str    目标字符串
     * @param length 截取长度
     * @return 截取后的字符串, 报错时返回""
     */
    public static String abbr(String str, int length) {
        if (isBlank(str)) {
            return EMPTY;
        }
        try {
            StringBuilder sb = new StringBuilder();
            int currentLength = 0;
            for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
                currentLength += String.valueOf(c).getBytes("GBK").length;
                if (currentLength <= length - 3) {
                    sb.append(c);
                } else {
                    sb.append("...");
                    break;
                }
            }
            return sb.toString();
        } catch (UnsupportedEncodingException e) {
            return EMPTY;
        }
    }

    /**
     * 驼峰命名法
     *
     * @param str       入参
     * @param separator 分隔符
     * @return hello_world -> helloWorld
     */
    public static String toCamelCase(String str, char separator) {
        if (isBlank(str)) {
            return EMPTY;
        }
        str = str.toLowerCase();
        StringBuilder sb = new StringBuilder(str.length());
        boolean upperCase = false;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (c == separator) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 驼峰命名法
     *
     * @param str       入参
     * @param separator 分隔符
     * @return hello_world -> HelloWorld
     */
    public static String toCapitalizeCamelCase(String str, char separator) {
        if (isBlank(str)) {
            return EMPTY;
        }
        str = toCamelCase(str, separator);
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 驼峰命名法
     *
     * @param str       入参
     * @param separator 分隔符
     * @return helloWorld -> hello_world
     */
    public static String toUnderlineCase(String str, char separator) {
        if (isBlank(str)) {
            return EMPTY;
        }
        StringBuilder sb = new StringBuilder();
        boolean upperCase = false;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            boolean nextUpperCase = true;
            if (i < (str.length() - 1)) {
                nextUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }
            if ((i > 0) && Character.isUpperCase(c)) {
                if (!upperCase || !nextUpperCase) {
                    sb.append(separator);
                }
                upperCase = true;
            } else {
                upperCase = false;
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }

    /**
     * 创建8位的随机码
     * 排除<p>小写字母 l o</p><p>大写字母 I O</p><p>数字 1 0</p>
     *
     * @return 随机密码
     */
    public static String createRandomCode(int codeLength, boolean isNum) {
        if (codeLength <= 0) {
            throw new BusinessException(ResultCodeEnum.LENGTH_ERROR);
        }
        char[] str = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k',
                'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
        char[] num = {'2', '3', '4', '5', '6', '7', '8', '9'};
        char[] result = isNum ? num : ArrayUtils.addAll(str, num);
        final int maxNum = str.length - 1;
        StringBuilder sb = new StringBuilder();
        int rdGet; //取得随机数
        ThreadLocalRandom rd = ThreadLocalRandom.current();
        int count = 0;
        while (count < codeLength) {
            //生成的数最大为60-1
            rdGet = Math.abs(rd.nextInt(maxNum));
            if (rdGet < result.length) {
                sb.append(result[rdGet]);
                count++;
            }
        }
        return sb.toString();
    }
}
